//
//  XGDemoViewController.m
//  HuanXin
//
//  Created by monkey on 2019/11/22.
//  Copyright © 2019 itcast. All rights reserved.
//

#import <Hyphenate/Hyphenate.h>
#import <JSQMessagesViewController/JSQMessages.h>
#import <SVProgressHUD/SVProgressHUD.h>
#import <TZImagePickerController/TZImagePickerController.h>
#import <MJRefresh/MJRefresh.h>
#import <MWPhotoBrowser.h>

#import "XGConversationViewController.h"
#import "XGMapViewController.h"

#import "XGChatMessageModel.h"

#import "XGVoiceRecorderView.h"

#import "XGAudioRecordHelper.h"
#import "NSString+NSHash.h"

@interface XGConversationViewController () <EMChatManagerDelegate,TZImagePickerControllerDelegate,XGVoiceRecorderViewDelegate,MWPhotoBrowserDelegate>
{
    /// 用户名
    NSString *_userName;
    /// 会话对象
    EMConversation *_conversation;
    /// 聊天信息数组
    NSMutableArray<XGChatMessageModel *> *_messageArrM;
    // 发送者信息气泡
    JSQMessagesBubbleImage *_outgoingBubbleImageData;
    // 好友信息气泡
    JSQMessagesBubbleImage *_incomingBubbleImageData;
    /// 头像
    JSQMessagesAvatarImage *_avatarImage;
    /// 图片浏览器数组
    NSMutableArray<XGChatMessageModel *> *_imageMessageArrM;
}
@end

@implementation XGConversationViewController

#pragma mark - 构造方法

- (instancetype)initWithUserName:(NSString *)userName
{
    if (self = [super initWithNibName:nil bundle:nil]) {
        _userName = [userName copy];
        [self initializeSetting];
    }
    
    return self;
}

+ (instancetype)conversationViewControllerWithUserName:(NSString *)userName
{
    return [[self alloc] initWithUserName:userName];
}

#pragma mark - 控制器生命周期方法

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.title = _userName;

    // 加载消息
    [self loadChatMessage:nil];
    
    // 注册cell操作
    [JSQMessagesCollectionViewCell registerMenuAction:@selector(delete:)];
    [JSQMessagesCollectionViewCell registerMenuAction:@selector(recallMessage:)];
    // 设置collectionView
    self.collectionView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1];
    self.collectionView.dataSource = self;
    // 设置下拉刷新
    __weak typeof(self) weakSelf = self;
    self.collectionView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf loadChatMessage:strongSelf->_messageArrM.firstObject.emmessage.messageId];
    }];
    self.collectionView.mj_header.automaticallyChangeAlpha = YES;
    // 注册消息回调
    [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    // 将所有消息置位已读
    if (_conversation.unreadMessagesCount > 0) {
        [_conversation markAllMessagesAsRead:nil];
        if (self.markAllCompletion) {
            self.markAllCompletion(_conversation.conversationId);
        }
    }
}

- (void)dealloc
{
    // 移除消息回调
    [[EMClient sharedClient].chatManager removeDelegate:self];
    DEBUG_Log_Method;
}

#pragma mark - EMChatManagerDelegate

// 收到好友消息
- (void)messagesDidReceive:(NSArray<EMMessage *> *)aMessages
{
    for (EMMessage *message in aMessages) {
        NSDate *date = [NSDate dateWithTimeIntervalInMilliSecondSince1970:message.localTime];
        if ([message.conversationId isEqualToString:_conversation.conversationId]) {
            // 发送消息已读回执
            [[EMClient sharedClient].chatManager sendMessageReadAck:message completion:nil];
            // 将消息置为已读
            [_conversation markMessageAsReadWithId:message.messageId error:nil];
            // 追加消息对象
            XGChatMessageModel *chatMessageModel = [XGChatMessageModel messageModelWithDate:date emmessage:message];
            [_messageArrM addObject:chatMessageModel];
            NSInteger index = _messageArrM.count - 1;
            
            if (message.body.type == EMMessageBodyTypeImage) {
                // 追加图片浏览器数组
                [_imageMessageArrM addObject:chatMessageModel];
                [[EMClient sharedClient].chatManager downloadMessageThumbnail:message progress:nil completion:^(EMMessage *message, EMError *error) {
                    // 刷新
                    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
                    [self->_messageArrM replaceObjectAtIndex:index withObject:[XGChatMessageModel messageModelWithDate:date emmessage:message]];
                    [self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
                }];
            } else if (message.body.type == EMMessageBodyTypeVoice) {
                // 语音消息自动进行下载
                EMFileMessageBody *fileBody = (EMFileMessageBody *)message.body;
                dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
                    while (fileBody.downloadStatus == EMDownloadStatusDownloading) {}
                    dispatch_async(dispatch_get_main_queue(), ^{
                        // 刷新
                        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
                        [self->_messageArrM replaceObjectAtIndex:index withObject:[XGChatMessageModel messageModelWithDate:date emmessage:message]];
                        [self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
                    });
                });
            }
        }
    }
    
    if (_messageArrM.count > 0) {
        [self finishReceivingMessageAnimated:YES];
    }
}

#pragma mark - JSQMessagesCollectionViewDataSource,JSQMessagesCollectionViewDelegateFlowLayout

// cell数量
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return _messageArrM.count;
}

// 每行的cell 先调用父类 然后再进行额外设置
- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
    JSQMessage *msg = _messageArrM[indexPath.item];
    if (!msg.isMediaMessage) {
        // 设置文本颜色
        if ([msg.senderId isEqualToString:self.senderId]) {
            cell.textView.textColor = [UIColor blackColor];
        }
        else {
            cell.textView.textColor = [UIColor whiteColor];
        }
        
        cell.textView.linkTextAttributes = @{NSForegroundColorAttributeName : cell.textView.textColor,
                                              NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
    }
    
    return cell;
}

// 发送者标识
- (NSString *)senderId
{
    return [EMClient sharedClient].currentUsername;
}

// 发送者用户名
- (NSString *)senderDisplayName
{
    return [EMClient sharedClient].currentUsername;
}

// 消息模型
- (id<JSQMessageData>)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return _messageArrM[indexPath.item];
}

// 消息气泡
- (id<JSQMessageBubbleImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
    JSQMessage *message = _messageArrM[indexPath.item];
    if ([message.senderId isEqualToString:self.senderId]) {
        return _outgoingBubbleImageData;
    }
    
    return _incomingBubbleImageData;
}

// 头像
- (id<JSQMessageAvatarImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return _avatarImage;
}

// cell顶部的富文本 常用于显示时间
- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.item % 3 == 0) {
        XGChatMessageModel *message = _messageArrM[indexPath.item];
        return [[NSAttributedString alloc] initWithString:message.time attributes:@{
            NSFontAttributeName: [UIFont systemFontOfSize:14],
            NSForegroundColorAttributeName: [UIColor lightGrayColor]
        }];
    }
    
    return nil;
}

// cell顶部文本的高度 通常是显示时间
- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView
                   layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath
{
    return indexPath.item % 3 == 0 ? kJSQMessagesCollectionViewCellLabelHeightDefault : 10;
}

// 点击发送按钮
- (void)didPressSendButton:(UIButton *)button withMessageText:(NSString *)text senderId:(NSString *)senderId senderDisplayName:(NSString *)senderDisplayName date:(NSDate *)date
{
    // 生成Message
    EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:text];
    NSString *from = [[EMClient sharedClient] currentUsername];
    EMMessage *message = [[EMMessage alloc] initWithConversationID:_conversation.conversationId from:from to:_userName body:body ext:nil];
    message.chatType = EMChatTypeChat; // 设置为单聊消息
    // 发送消息
    [self sendEMMessage:message];
}

// 点击附件按钮
- (void)didPressAccessoryButton:(UIButton *)sender
{
    __weak typeof(self) weakSelf = self;
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"菜单" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    
    // 发送文本
    [alert addAlertActionWithTitle:@"发送文本" action:^(UIAlertAction *action) {
        if (weakSelf.inputToolbar.contentView.textView.inputView) {
            weakSelf.inputToolbar.contentView.textView.inputView = nil;
            [weakSelf.inputToolbar.contentView.textView reloadInputViews];
        }
    } style:UIAlertActionStyleDefault];
    
    // 发送照片
    [alert addAlertActionWithTitle:@"发送照片" action:^(UIAlertAction *action) {
        [weakSelf dismissViewControllerAnimated:YES completion:^{
            TZImagePickerController *picker = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self];
            [weakSelf presentViewController:picker animated:YES completion:nil];
        }];
    } style:UIAlertActionStyleDefault];
    
    // 发送语音
    [alert addAlertActionWithTitle:@"发送语音" action:^(UIAlertAction *action) {
        [weakSelf dismissViewControllerAnimated:YES completion:^{
            XGVoiceRecorderView *voiceRecorderView = [[XGVoiceRecorderView alloc] initWithFrame:CGRectMake(0, 0, weakSelf.view.bounds.size.width, 180)];
            voiceRecorderView.delegate = self;
              
            // 刷新键盘视图
            weakSelf.inputToolbar.contentView.textView.inputView = voiceRecorderView;
            [weakSelf.inputToolbar.contentView.textView reloadInputViews];
            // 如果当前不是响应者 成为第一响应者
            if (![weakSelf.inputToolbar.contentView.textView isFirstResponder]) {
                [weakSelf.inputToolbar.contentView.textView becomeFirstResponder];
            }
        }];
    } style:UIAlertActionStyleDefault];
    
    // 发送位置
    [alert addAlertActionWithTitle:@"发送位置" action:^(UIAlertAction *action) {
        [weakSelf dismissViewControllerAnimated:YES completion:^{
            XGMapViewController *mapViewController = [[XGMapViewController alloc] init];
            [mapViewController setSendLocationCallBack:^(CLPlacemark *placemark) {
                [weakSelf sendLocationMessage:placemark];
            }];
            UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController: mapViewController];
            [weakSelf presentViewController:nav animated:YES completion:nil];
        }];
    } style:UIAlertActionStyleDefault];
    
    // 取消
    [alert addAlertActionWithTitle:@"取消" action:^(UIAlertAction *action) {
        [weakSelf dismissViewControllerAnimated:YES completion:nil];
    } style:UIAlertActionStyleDestructive];
    
    [self presentViewController:alert animated:YES completion:nil];
}

// 点击删除消息
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didDeleteMessageAtIndexPath:(NSIndexPath *)indexPath
{
    XGChatMessageModel *message = _messageArrM[indexPath.item];
    [_conversation deleteMessageWithId:message.emmessage.messageId error:nil];
    [_messageArrM removeObjectAtIndex:indexPath.item];
}

// 自定义cell操作
- (void)didReceiveMenuWillShowNotification:(NSNotification *)notification
{
    UIMenuController *menu = [notification object];
    menu.menuItems = @[[[UIMenuItem alloc] initWithTitle:@"撤回" action:@selector(recallMessage:)]];
    [super didReceiveMenuWillShowNotification:notification];
}

// cell是否可以响应动作
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
    if (action == @selector(recallMessage:)) {
        return YES;
    }

    return [super collectionView:collectionView canPerformAction:action forItemAtIndexPath:indexPath withSender:sender];
}

// cell响应动作
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
    if (action == @selector(recallMessage:)) {
        [self recallMessage:_messageArrM[indexPath.item]];
        return;
    }

    [super collectionView:collectionView performAction:action forItemAtIndexPath:indexPath withSender:sender];
}

// 撤回信息
- (void)recallMessage:(XGChatMessageModel *)message
{
    [[EMClient sharedClient].chatManager recallMessage:message.emmessage completion:^(EMMessage *aMessage, EMError *aError) {
        if (aError) {
            DEBUG_Log(@"无法撤回");
            [SVProgressHUD showErrorWithStatus:@"消息超时,无法撤回!"];
            return;
        }
        
        // 撤回...
        DEBUG_Log(@"撤回成功");
        [self->_messageArrM removeObject:message];
        [self.collectionView reloadData];
    }];
}

// 点击气泡回调
- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath
{
    XGChatMessageModel *messageModel = _messageArrM[indexPath.item];
    if (messageModel.emmessage.body.type == EMMessageBodyTypeImage) {
        // 点图片
        NSUInteger index = [_imageMessageArrM indexOfObject:messageModel];
        MWPhotoBrowser *photoBrowser = [[MWPhotoBrowser alloc] initWithDelegate:self];
        [photoBrowser setCurrentPhotoIndex:index];
        [self.navigationController pushViewController:photoBrowser animated:YES];
    } else {
        if (messageModel.emmessage.ext != nil) {
            // 点击位置信息
            CLLocationDegrees latitude = [messageModel.emmessage.ext[@"latitude"] doubleValue];
            CLLocationDegrees longitude = [messageModel.emmessage.ext[@"longitude"] doubleValue];
            XGMapViewController *mapViewController = [[XGMapViewController alloc] initWithLongitude:longitude latitude:latitude];
            UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController: mapViewController];
            [self presentViewController:nav animated:YES completion:nil];
            return;
        }
        
        // 点其他
        DEBUG_Log(@"点其他");
    }
}

#pragma mark - TZImagePickerControllerDelegate

// 相册图片选择完成
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto
{
    UIImage *image = photos.firstObject;
    NSData *data = UIImagePNGRepresentation(image);
    if (!data) {
        return;
    }
    
    // 生成Message
    EMImageMessageBody *body = [[EMImageMessageBody alloc] initWithData:data displayName:@"image.png"];
    // body.compressionRatio = 1.0f; 1.0表示发送原图不压缩。默认值是0.6，压缩的倍数是0.6倍
    NSString *from = [[EMClient sharedClient] currentUsername];
    EMMessage *message = [[EMMessage alloc] initWithConversationID:_conversation.conversationId from:from to:_userName body:body ext:nil];
    message.chatType = EMChatTypeChat;
    // 发送消息
    [self sendEMMessage:message];
}

#pragma mark - MWPhotoBrowserDelegate

// 多少张图片
- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser
{
    return _imageMessageArrM.count;
}

// 具体对应某一张图片
- (id<MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index
{
    NSString *url = [(EMImageMessageBody *)_imageMessageArrM[index].emmessage.body remotePath];
    return [MWPhoto photoWithURL: [NSURL URLWithString:url]];
}

#pragma mark - XGVoiceRecorderViewDelegate

// 开始点击录音按钮
- (void)recorderVoiceButtonTouchDown:(XGVoiceRecorderView *)voiceRecorderView
{
    NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).lastObject;
    NSString *fileName = [[[NSDate date] stringWithFormat:@"yyyy-MM-dd HH:mm:ss"] MD5];
    NSString *filePath = [cachePath stringByAppendingPathComponent:fileName];
    [[XGAudioRecordHelper sharedHelper] startRecordWithPath:filePath completion:^(NSError *error) {
        if (error) {
            DEBUG_Log(@"开始录音失败");
            return;
        }
        
        DEBUG_Log(@"开始录音");
    }];
}

// 按钮内停止点击
- (void)recorderVoiceButtonUpInside:(XGVoiceRecorderView *)voiceRecorderView
{
    [[XGAudioRecordHelper sharedHelper] stopRecordWithCompletion:^(NSString *aPath, NSInteger aTimeLength) {
        if (aPath == nil || aTimeLength == 0) {
            DEBUG_Log(@"录音失败");
            return;
        }
        
        // 发送语音消息
        EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithLocalPath:aPath displayName:@"audio"];
        body.duration = (NSTimeInterval)aTimeLength;
        NSString *from = [[EMClient sharedClient] currentUsername];
        EMMessage *message = [[EMMessage alloc] initWithConversationID:self->_conversation.conversationId from:from to:self->_userName body:body ext:nil];
        message.chatType = EMChatTypeChat;
        [self sendEMMessage:message];
    }];
}

// 按钮外停止点击
- (void)recorderVoiceButtonTouchOutside:(XGVoiceRecorderView *)voiceRecorderView
{
    [[XGAudioRecordHelper sharedHelper] cancelRecord];
}

// 按钮取消点击
- (void)recorderVoiceButtonCancelTouch:(XGVoiceRecorderView *)voiceRecorderView
{
    [[XGAudioRecordHelper sharedHelper] cancelRecord];
}

#pragma mark - 其他方法

// 发送位置信息
- (void)sendLocationMessage:(CLPlacemark *)placemark
{
    if (placemark == nil) {
        return;
    }
    
    NSString *from = [EMClient sharedClient].currentUsername;
    NSString *text = [NSString stringWithFormat:@"[位置信息] %@ %@ %@",placemark.locality,placemark.subLocality,placemark.name];
    // 生成Message
    EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:text];
    EMMessage *message = [[EMMessage alloc] initWithConversationID:_conversation.conversationId from:from to:_userName body:body ext:@{
        @"latitude": @(placemark.location.coordinate.latitude),
        @"longitude": @(placemark.location.coordinate.longitude)
    }];
    message.chatType = EMChatTypeChat; // 设置为单聊消息
    // 发送消息
    [self sendEMMessage:message];
}

/// 初初始化设置
- (void)initializeSetting
{
    // 会话对象
    _conversation = [[EMClient sharedClient].chatManager getConversation:_userName type:EMConversationTypeChat createIfNotExist:YES];
    // 发送者气泡
    JSQMessagesBubbleImageFactory *bubbleFactory = [[JSQMessagesBubbleImageFactory alloc] init];
    _outgoingBubbleImageData = [bubbleFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleLightGrayColor]];
    // 好友气泡
    _incomingBubbleImageData = [bubbleFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
    // 头像
    _avatarImage = [JSQMessagesAvatarImageFactory avatarImageWithImage:[UIImage imageNamed:@"user_avatar_blue"] diameter:kJSQMessagesCollectionViewAvatarSizeDefault];
    _messageArrM = [NSMutableArray array];
    _imageMessageArrM = [NSMutableArray array];
}

/// 加载聊天信息
/// @param messageId 信息id
- (void)loadChatMessage:(NSString *)messageId
{
    [_conversation loadMessagesStartFromId:messageId count:10 searchDirection:EMMessageSearchDirectionUp completion:^(NSArray *aMessages, EMError *aError) {
        // 停止下拉刷新
        if ([self.collectionView.mj_header isRefreshing]) {
            [self.collectionView.mj_header endRefreshing];
        }
        
        if (aError || aMessages.count == 0) {
            DEBUG_Log(@"没有更多聊天信息");
            return;
        }
        
        NSMutableArray<XGChatMessageModel *> *chatMessageArrM = [NSMutableArray arrayWithCapacity:aMessages.count + self->_messageArrM.count];
        for (EMMessage *message in aMessages) {
            NSDate *date = [NSDate dateWithTimeIntervalInMilliSecondSince1970:message.localTime];
            XGChatMessageModel *chatMessageModel = [XGChatMessageModel messageModelWithDate:date emmessage:message];
            [chatMessageArrM addObject: chatMessageModel];
            
            if (message.body.type == EMMessageBodyTypeImage) {
                [self->_imageMessageArrM addObject:chatMessageModel];
            }
        }
        
        // messageId有值 加载更多聊天数据 新加载的数据放在前面
        if (messageId != nil) {
            [chatMessageArrM addObjectsFromArray:self->_messageArrM];
        }
        
        self->_messageArrM = chatMessageArrM;
        [self.collectionView reloadData];
    }];
}

/// 发送消息
/// @param message 消息对象
- (void)sendEMMessage:(EMMessage *)message
{
    [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:^(EMMessage *message, EMError *error) {
        if (error) {
            [SVProgressHUD showErrorWithStatus:@"发送消息失败"];
            return;
        }
        
        // 本地发送消息
        XGChatMessageModel *chatMessageModel = [XGChatMessageModel messageModelWithDate:[NSDate date] emmessage:message];
        [self->_messageArrM addObject:chatMessageModel];
        // 如果是图片消息 追加图片浏览器数组
        if (message.body.type == EMMessageBodyTypeImage) {
            [self->_imageMessageArrM addObject:chatMessageModel];
        }
        [self finishSendingMessageAnimated:YES];
    }];
}

@end
